package cs.rsa.ts14.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Builds and executes Vagrant commands
 */
public class VagrantHelper {

	private final static String STATUS_RUNNING = "running";
	private final static String STATUS_SAVED = "saved";
	private final static String STATUS_POWER_OFF = "poweroff";

	private final static String DEFAULT_VM = "default";

	private List<String> commands;
	private String vm;

	private String vagrantFolder;

	private VagrantHelper() {
		commands = new ArrayList<>();
		vm = "";
	}

	private VagrantHelper(String vagrantFolder) {
		commands = new ArrayList<>();
		vm = "";
		this.vagrantFolder = vagrantFolder;
	}

	public static VagrantHelper create(String vagrantFolder) {
		return new VagrantHelper(vagrantFolder);
	}

	public static VagrantHelper create() {
		return new VagrantHelper();
	}

	public String execute() {
		String shellCommand = "";
		if (!commands.isEmpty()) {

			if (vagrantFolder != null && vagrantFolder.length() > 0) {
				shellCommand = "cd " + vagrantFolder + " & ";
			}

			Iterator<String> it = commands.iterator();
			while (it.hasNext()) {
				shellCommand += it.next();
				if (it.hasNext()) {
					shellCommand += " & ";
				}
			}
		}
		System.out.println("Executing command:\n\t" + shellCommand);
		System.out.println("\tSTART");
		Timer timer = new Timer();
		timer.start();

		String output = ShellHelper.execute(shellCommand, System.out);

		timer.end();
		long totalTime = timer.getTotalTime();
		int sec = (int) (totalTime / 1000) % 60;
		int min = (int) ((totalTime / (1000 * 60)) % 60);
		int hr = (int) ((totalTime / (1000 * 60 * 60)) % 24);

		System.out.println("Executing command:\n\t" + shellCommand);
		System.out.println("\tEND\ttime taken: "
				+ String.format("%02d:%02d:%02d", hr, min, sec));
		return output;
	}
	
	public VagrantHelper env(String name, String value) {
		commands.add("set " + name + "=" + value);
		return this;
	}
	
	/**
	 * Sets the context VM in a multi-VM Vagrantfile. Do not use if only one,
	 * unnamed VM in Vagrantfile.
	 * 
	 * @param vm
	 * @return
	 */
	public VagrantHelper vm(String vm) {
		this.vm = vm;
		return this;
	}

	/**
	 * Commands after this will be for all VMs
	 * 
	 * @return
	 */
	public VagrantHelper vm() {
		this.vm = "";
		return this;
	}

	public VagrantHelper up() {
		commands.add("vagrant up " + vm);
		return this;
	}

	public VagrantHelper suspend() {
		commands.add("vagrant suspend " + vm);
		return this;
	}

	public VagrantHelper resume() {
		commands.add("vagrant resume " + vm);
		return this;
	}

	public VagrantHelper halt() {
		commands.add("vagrant halt " + vm);
		return this;
	}

	public VagrantHelper destroy() {
		commands.add("vagrant destroy -f " + vm);
		return this;
	}

	public VagrantHelper sshCmd( String cmd ) {
		commands.add("vagrant ssh " + vm + " -c \"" + cmd +"\"" );
		return this;
	}
	
	public VagrantHelper status() {
		commands.add("vagrant status " + vm);
		return this;
	}

	public boolean vmExists() {
		if (vm.length() == 0) {
			this.vm(DEFAULT_VM);
		}

		String result;
		result = this.status().execute();
		result = result.replace(" ", "");
		if (result.contains(vm + STATUS_RUNNING)
				|| result.contains(vm + STATUS_SAVED)
				|| result.contains(vm + STATUS_POWER_OFF)) {
			return true;
		}
		return false;
	}

	public VagrantHelper snapshotTake(String snapshotName) {
		commands.add("vagrant snapshot take " + vm + " " + snapshotName);
		return this;
	}

	public VagrantHelper snapshotGo(String snapshotName) {
		commands.add("vagrant snapshot go " + vm + " " + snapshotName);
		return this;
	}

	public VagrantHelper snapshotList() {
		commands.add("vagrant snapshot list " + vm);
		return this;
	}

	public boolean snapshotExists(String snapshotName) {
		String result;
		result = this.snapshotList().execute();
		if (result.contains(snapshotName)) {
			return true;
		}
		return false;
	}
}
